/**
 * create by zhang_tian_xiao, 2018/4/20 1:33
 *
 * */
package com.ax.framework.jfinal.db

import com.jfinal.kit.StrKit
import com.jfinal.plugin.activerecord.dialect.OracleDialect
import com.jfinal.plugin.activerecord.generator.ColumnMeta
import com.jfinal.plugin.activerecord.generator.MetaBuilder
import com.jfinal.plugin.activerecord.generator.TableMeta
import java.sql.ResultSet
import java.sql.SQLException
import java.sql.Types
import javax.sql.DataSource

class MetaBuilder(ds: DataSource) : MetaBuilder(ds) {

    @Throws(SQLException::class)
    override fun buildColumnMetas(tableMeta: TableMeta) {
        val sql = this.dialect.forTableBuilderDoBuild(tableMeta.name)
        val stm = this.conn.createStatement()
        val rs = stm.executeQuery(sql)
        val rsmd = rs.metaData

        for (i in 1..rsmd.columnCount) {


            val cm = ColumnMeta()
            cm.name = rsmd.getColumnName(i)
            var typeStr: String? = null
            var type: Int? = null
            if (this.dialect.isKeepByteAndShort) {
                type = rsmd.getColumnType(i)
                if (type == -6) {
                    typeStr = "java.lang.Byte"
                } else if (type == 5) {
                    typeStr = "java.lang.Short"
                }
            }

            if (typeStr == null) {
                val colClassName = rsmd.getColumnClassName(i)
                typeStr = this.typeMapping.getType(colClassName)
            }

            if (typeStr == null) {
                type = rsmd.getColumnType(i)
                if (type != -2 && type != -3 && type != -4 && type != 2004) {
                    if (type != 2005 && type != 2011) {
                        if (type != 93 && type != 91) {
                            if (type == 1111) {
                                typeStr = "com.alibaba.fastjson.JSONObject"
                            }
                            //数组类型
                            else if (type == Types.ARRAY) {
                                //目前只用到这几种
                                val columnTypeName = rsmd.getColumnTypeName(i)
                                //String
                                if ("_text" == columnTypeName) {
                                    typeStr = "java.lang.String[]"
                                }
                                //integer
                                else if ("_int4" == columnTypeName) {
                                    typeStr = "java.lang.Integer[]"
                                }
                                //long
                                else if ("_int8" == columnTypeName) {
                                    typeStr = "java.lang.Long[]"
                                }
                                //JSONArray
                                else if ("_jsonb" == columnTypeName) {
                                    typeStr = "com.alibaba.fastjson.JSONArray"
                                }
                                //
                                else {
                                    typeStr = "java.lang.String"
                                }
                            } else {
                                typeStr = "java.lang.String"
                            }
                        } else {
                            typeStr = "java.util.Date"
                        }
                    } else {
                        typeStr = "java.lang.String"
                    }
                } else {
                    typeStr = "byte[]"
                }
            }
            cm.javaType = typeStr
            cm.attrName = this.buildAttrName(cm.name)
            //println("${type ?: 999999}  $typeStr  ${cm.attrName} ")
            tableMeta.columnMetas.add(cm)
        }

        rs.close()
        stm.close()
    }

    override fun getTablesResultSet(): ResultSet {
        val schemaPattern = if (this.dialect is OracleDialect) this.dbMeta.userName else null
        return this.dbMeta.getTables(this.conn.catalog, "public", null as String?, arrayOf("TABLE"))
    }

    /*
    *  扩展
    * */
    override protected fun buildTableNames(ret: MutableList<TableMeta>) {
        val rs = tablesResultSet
        while (rs.next()) {
            val tableName = rs.getString("TABLE_NAME")

            if (excludedTables.contains(tableName)) {
                println("Skip table :$tableName")
                continue
            }
            if (isSkipTable(tableName)) {
                println("Skip table :$tableName")
                continue
            }

            if (excludedTables.any { it.toRegex().matches(tableName) }) {
                println("Skip table :$tableName")
                continue
            }

            val tableMeta = TableMeta()
            tableMeta.name = tableName
            tableMeta.remarks = rs.getString("REMARKS")

            tableMeta.modelName = buildModelName(tableName)
            tableMeta.baseModelName = buildBaseModelName(tableMeta.modelName)
            ret.add(tableMeta)
        }
        rs.close()
    }

    override protected fun buildPrimaryKey(tableMeta: TableMeta) {
        val rs = dbMeta.getPrimaryKeys(conn.catalog, null, tableMeta.name)

        var primaryKey = ""
        var index = 0
        while (rs.next()) {
            if (index++ > 0) {
                primaryKey += ","
            }
            primaryKey += rs.getString("COLUMN_NAME")
        }
        if (StrKit.isBlank(primaryKey)) {
            System.err.println("primaryKey of table \"" + tableMeta.name + "\" required by active record pattern")
        }
        tableMeta.primaryKey = primaryKey
        rs.close()
    }

}